package com.sch.www.codeGenerator.dao.plugin;


import org.mybatis.generator.api.*;
import org.mybatis.generator.exception.ShellException;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.mybatis.generator.internal.DomWriter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

//import    org.mybatis.generator.api.dom.xml.Document;

public class GenerateManualXmlPlugin extends PluginAdapter {
    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        File targetFile;
        String source;
        try {
            ShellCallback shellCallback = new DefaultShellCallback(true);
            File directory = shellCallback.getDirectory(sqlMap
                    .getTargetProject(), sqlMap.getTargetPackage());

            File manualDirectory = new File(directory.getParentFile(), "manual");
            if (!manualDirectory.exists()) {
                manualDirectory.mkdirs();
            }

            targetFile = new File(manualDirectory, sqlMap.getFileName());
            source = sqlMap.getFormattedContent();
            InputSource in = new InputSource(new StringReader(source));

            if (!targetFile.exists()) {

                DocumentBuilderFactory factory = DocumentBuilderFactory
                        .newInstance();
                factory.setExpandEntityReferences(false);
                DocumentBuilder builder = factory.newDocumentBuilder();

                Document document = builder.parse(in);

                Element rootElement = document.getDocumentElement();

                List<Node> nodesToDelete = new ArrayList<>();
                NodeList children = rootElement.getChildNodes();
                for (int i = 0; i < children.getLength(); i++) {
                    Node node = children.item(i);
                    nodesToDelete.add(node);
                }
                for (Node node : nodesToDelete) {
                    rootElement.removeChild(node);
                }
                source = prettyPrint(document);
                writeFile(targetFile, source, "UTF-8"); //$NON-NLS-1$


//
//
//                rootElement.removeChild()
//


//                // reconcile the root element attributes -
//                // take all attributes from the new element and add to the existing
//                // element
//
//                // remove all attributes from the existing root element
//                NamedNodeMap attributes = existingRootElement.getAttributes();
//                int attributeCount = attributes.getLength();
//                for (int i = attributeCount - 1; i >= 0; i--) {
//                    Node node = attributes.item(i);
//                    existingRootElement.removeAttribute(node.getNodeName());
//                }
//
//                // add attributes from the new root node to the old root node
//                attributes = newRootElement.getAttributes();
//                attributeCount = attributes.getLength();
//                for (int i = 0; i < attributeCount; i++) {
//                    Node node = attributes.item(i);
//                    existingRootElement.setAttribute(node.getNodeName(), node
//                            .getNodeValue());
//                }
//
//                // remove the old generated elements and any
//                // white space before the old nodes
//                List<Node> nodesToDelete = new ArrayList<Node>();
//                NodeList children = existingRootElement.getChildNodes();
//                int length = children.getLength();
//                for (int i = 0; i < length; i++) {
//                    Node node = children.item(i);
//                    if (isGeneratedNode(node)) {
//                        nodesToDelete.add(node);
//                    } else if (isWhiteSpace(node)
//                            && isGeneratedNode(children.item(i + 1))) {
//                        nodesToDelete.add(node);
//                    }
//                }
//
//                for (Node node : nodesToDelete) {
//                    existingRootElement.removeChild(node);
//                }
//
//                // add the new generated elements
//                children = newRootElement.getChildNodes();
//                length = children.getLength();
//                Node firstChild = existingRootElement.getFirstChild();
//                for (int i = 0; i < length; i++) {
//                    Node node = children.item(i);
//                    // don't add the last node if it is only white space
//                    if (i == length - 1) {
//                        if (isWhiteSpace(node)) {
//                            break;
//                        }
//                    }
//
//                    Node newNode = existingDocument.importNode(node, true);
//                    if (firstChild == null) {
//                        existingRootElement.appendChild(newNode);
//                    } else {
//                        existingRootElement.insertBefore(newNode, firstChild);
//                    }
//                }
//
//                // pretty print the result
//                return prettyPrint(existingDocument);

//                writeFile(addTargetFile, addSource, gjf.getFileEncoding());
            }

            //++++++++++++++++++++++++++++++++++++++++++++++++++++++
        } catch (Exception e) {
        }


        return true;
    }


    private void writeFile(File file, String content, String fileEncoding) throws IOException {
        FileOutputStream fos = new FileOutputStream(file, false);
        OutputStreamWriter osw;
        if (fileEncoding == null) {
            osw = new OutputStreamWriter(fos);
        } else {
            osw = new OutputStreamWriter(fos, fileEncoding);
        }

        BufferedWriter bw = new BufferedWriter(osw);
        bw.write(content);
        bw.close();
    }

    private static String prettyPrint(Document document) throws ShellException {
        DomWriter dw = new DomWriter();
        String s = dw.toString(document);
        return s;
    }
}
